// Copyright Epic Games, Inc. All Rights Reserved.

#include "LyraEquipmentManagerComponent.h"

#include "AbilitySystem/LyraAbilitySystemComponent.h"
#include "AbilitySystemGlobals.h"
#include "Engine/ActorChannel.h"
#include "LyraEquipmentDefinition.h"
#include "LyraEquipmentInstance.h"
#include "Net/UnrealNetwork.h"

#include UE_INLINE_GENERATED_CPP_BY_NAME(LyraEquipmentManagerComponent)

class FLifetimeProperty;
struct FReplicationFlags;

//////////////////////////////////////////////////////////////////////
// FLyraAppliedEquipmentEntry

/**
 * 获取调试字符串
 * @return 调试字符串
 */
FString FLyraAppliedEquipmentEntry::GetDebugString() const
{
	return FString::Printf(TEXT("%s of %s"), *GetNameSafe(Instance), *GetNameSafe(EquipmentDefinition.Get())); // 返回实例和定义的名称
}

//////////////////////////////////////////////////////////////////////
// FLyraEquipmentList

/**
 * 复制移除前调用
 * @param RemovedIndices - 被移除的索引数组视图
 * @param FinalSize - 最终大小
 */
void FLyraEquipmentList::PreReplicatedRemove(const TArrayView<int32> RemovedIndices, int32 FinalSize)
{
 	for (int32 Index : RemovedIndices) // 遍历被移除的索引
 	{
 		const FLyraAppliedEquipmentEntry& Entry = Entries[Index]; // 获取条目
		if (Entry.Instance != nullptr) // 检查实例有效性
		{
			Entry.Instance->OnUnequipped(); // 调用卸下方法
		}
 	}
}

/**
 * 复制添加后调用
 * @param AddedIndices - 被添加的索引数组视图
 * @param FinalSize - 最终大小
 */
void FLyraEquipmentList::PostReplicatedAdd(const TArrayView<int32> AddedIndices, int32 FinalSize)
{
	for (int32 Index : AddedIndices) // 遍历被添加的索引
	{
		const FLyraAppliedEquipmentEntry& Entry = Entries[Index]; // 获取条目
		if (Entry.Instance != nullptr) // 检查实例有效性
		{
			Entry.Instance->OnEquipped(); // 调用装备方法
		}
	}
}

/**
 * 复制更改后调用
 * @param ChangedIndices - 被更改的索引数组视图
 * @param FinalSize - 最终大小
 */
void FLyraEquipmentList::PostReplicatedChange(const TArrayView<int32> ChangedIndices, int32 FinalSize)
{
// 	for (int32 Index : ChangedIndices)
// 	{
// 		const FGameplayTagStack& Stack = Stacks[Index];
// 		TagToCountMap[Stack.Tag] = Stack.StackCount;
// 	}
}

/**
 * 获取能力系统组件
 * @return 能力系统组件
 */
ULyraAbilitySystemComponent* FLyraEquipmentList::GetAbilitySystemComponent() const
{
	check(OwnerComponent); // 检查所有者组件有效性
	AActor* OwningActor = OwnerComponent->GetOwner(); // 获取所有者演员
	return Cast<ULyraAbilitySystemComponent>(UAbilitySystemGlobals::GetAbilitySystemComponentFromActor(OwningActor)); // 从演员获取能力系统组件
}

/**
 * 添加装备条目
 * @param EquipmentDefinition - 装备定义类
 * @return 创建的装备实例
 */
ULyraEquipmentInstance* FLyraEquipmentList::AddEntry(TSubclassOf<ULyraEquipmentDefinition> EquipmentDefinition)
{
	ULyraEquipmentInstance* Result = nullptr;

	check(EquipmentDefinition != nullptr); // 检查装备定义有效性
 	check(OwnerComponent); // 检查所有者组件有效性
	check(OwnerComponent->GetOwner()->HasAuthority()); // 检查权威端
	
	const ULyraEquipmentDefinition* EquipmentCDO = GetDefault<ULyraEquipmentDefinition>(EquipmentDefinition); // 获取装备定义默认对象

	TSubclassOf<ULyraEquipmentInstance> InstanceType = EquipmentCDO->InstanceType; // 获取实例类型
	if (InstanceType == nullptr) // 如果实例类型为空
	{
		InstanceType = ULyraEquipmentInstance::StaticClass(); // 使用默认实例类型
	}
	
	FLyraAppliedEquipmentEntry& NewEntry = Entries.AddDefaulted_GetRef(); // 添加默认条目并获取引用
	NewEntry.EquipmentDefinition = EquipmentDefinition; // 设置装备定义
	NewEntry.Instance = NewObject<ULyraEquipmentInstance>(OwnerComponent->GetOwner(), InstanceType);  //@TODO: 由于 UE-127172，使用演员而不是组件作为外部对象
	Result = NewEntry.Instance; // 设置返回值

	if (ULyraAbilitySystemComponent* ASC = GetAbilitySystemComponent()) // 获取能力系统组件
	{
		for (const TObjectPtr<const ULyraAbilitySet>& AbilitySet : EquipmentCDO->AbilitySetsToGrant) // 遍历要授予的能力集
		{
			AbilitySet->GiveToAbilitySystem(ASC, /*inout*/ &NewEntry.GrantedHandles, Result); // 授予能力集
		}
	}
	else
	{
		//@TODO: 警告日志？
	}

	Result->SpawnEquipmentActors(EquipmentCDO->ActorsToSpawn); // 生成装备演员

	MarkItemDirty(NewEntry); // 标记条目为脏

	return Result; // 返回结果
}

/**
 * 移除装备条目
 * @param Instance - 要移除的装备实例
 */
void FLyraEquipmentList::RemoveEntry(ULyraEquipmentInstance* Instance)
{
	for (auto EntryIt = Entries.CreateIterator(); EntryIt; ++EntryIt) // 遍历条目迭代器
	{
		FLyraAppliedEquipmentEntry& Entry = *EntryIt; // 获取条目引用
		if (Entry.Instance == Instance) // 检查实例匹配
		{
			if (ULyraAbilitySystemComponent* ASC = GetAbilitySystemComponent()) // 获取能力系统组件
			{
				Entry.GrantedHandles.TakeFromAbilitySystem(ASC); // 从能力系统收回授予的能力
			}

			Instance->DestroyEquipmentActors(); // 销毁装备演员
			

			EntryIt.RemoveCurrent(); // 移除当前条目
			MarkArrayDirty(); // 标记数组为脏
		}
	}
}

//////////////////////////////////////////////////////////////////////
// ULyraEquipmentManagerComponent

/**
 * 构造函数
 * @param ObjectInitializer - 对象初始化器
 */
ULyraEquipmentManagerComponent::ULyraEquipmentManagerComponent(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
	, EquipmentList(this) // 初始化装备列表
{
	SetIsReplicatedByDefault(true); // 默认启用复制
	bWantsInitializeComponent = true; // 需要初始化组件
}

/**
 * 注册生命周期复制属性
 * @param OutLifetimeProps - 输出生命周期属性数组
 */
void ULyraEquipmentManagerComponent::GetLifetimeReplicatedProps(TArray< FLifetimeProperty >& OutLifetimeProps) const
{
	Super::GetLifetimeReplicatedProps(OutLifetimeProps); // 调用父类方法

	DOREPLIFETIME(ThisClass, EquipmentList); // 复制 EquipmentList
}

/**
 * 装备物品
 * @param EquipmentClass - 装备定义类
 * @return 装备实例
 */
ULyraEquipmentInstance* ULyraEquipmentManagerComponent::EquipItem(TSubclassOf<ULyraEquipmentDefinition> EquipmentClass)
{
	ULyraEquipmentInstance* Result = nullptr;
	if (EquipmentClass != nullptr) // 检查装备类有效性
	{
		Result = EquipmentList.AddEntry(EquipmentClass); // 添加装备条目
		if (Result != nullptr) // 检查结果有效性
		{
			Result->OnEquipped(); // 调用装备方法

			if (IsUsingRegisteredSubObjectList() && IsReadyForReplication()) // 检查使用注册子对象列表和准备复制
			{
				AddReplicatedSubObject(Result); // 添加复制子对象
			}
		}
	}
	return Result; // 返回结果
}

/**
 * 卸下物品
 * @param ItemInstance - 要卸下的装备实例
 */
void ULyraEquipmentManagerComponent::UnequipItem(ULyraEquipmentInstance* ItemInstance)
{
	if (ItemInstance != nullptr) // 检查实例有效性
	{
		if (IsUsingRegisteredSubObjectList()) // 检查使用注册子对象列表
		{
			RemoveReplicatedSubObject(ItemInstance); // 移除复制子对象
		}

		ItemInstance->OnUnequipped(); // 调用卸下方法
		EquipmentList.RemoveEntry(ItemInstance); // 移除装备条目
	}
}

/**
 * 复制子对象
 * @param Channel - 演员通道
 * @param Bunch - 输出数据包
 * @param RepFlags - 复制标志
 * @return 是否写入数据
 */
bool ULyraEquipmentManagerComponent::ReplicateSubobjects(UActorChannel* Channel, class FOutBunch* Bunch, FReplicationFlags* RepFlags)
{
	bool WroteSomething = Super::ReplicateSubobjects(Channel, Bunch, RepFlags); // 调用父类方法

	for (FLyraAppliedEquipmentEntry& Entry : EquipmentList.Entries) // 遍历装备条目
	{
		ULyraEquipmentInstance* Instance = Entry.Instance; // 获取实例

		if (IsValid(Instance)) // 检查实例有效性
		{
			WroteSomething |= Channel->ReplicateSubobject(Instance, *Bunch, *RepFlags); // 复制子对象
		}
	}

	return WroteSomething; // 返回是否写入数据
}

/**
 * 初始化组件
 */
void ULyraEquipmentManagerComponent::InitializeComponent()
{
	Super::InitializeComponent(); // 调用父类方法
}

/**
 * 取消初始化组件
 */
void ULyraEquipmentManagerComponent::UninitializeComponent()
{
	TArray<ULyraEquipmentInstance*> AllEquipmentInstances; // 所有装备实例数组

	// 在移除之前收集所有实例，以避免影响装备列表迭代器的副作用	
	for (const FLyraAppliedEquipmentEntry& Entry : EquipmentList.Entries) // 遍历装备条目
	{
		AllEquipmentInstances.Add(Entry.Instance); // 添加实例到数组
	}

	for (ULyraEquipmentInstance* EquipInstance : AllEquipmentInstances) // 遍历所有装备实例
	{
		UnequipItem(EquipInstance); // 卸下物品
	}

	Super::UninitializeComponent(); // 调用父类方法
}

/**
 * 准备复制
 */
void ULyraEquipmentManagerComponent::ReadyForReplication()
{
	Super::ReadyForReplication(); // 调用父类方法

	// 注册现有的 LyraEquipmentInstances
	if (IsUsingRegisteredSubObjectList()) // 检查使用注册子对象列表
	{
		for (const FLyraAppliedEquipmentEntry& Entry : EquipmentList.Entries) // 遍历装备条目
		{
			ULyraEquipmentInstance* Instance = Entry.Instance; // 获取实例

			if (IsValid(Instance)) // 检查实例有效性
			{
				AddReplicatedSubObject(Instance); // 添加复制子对象
			}
		}
	}
}

/**
 * 获取类型的第一个实例
 * @param InstanceType - 实例类型
 * @return 第一个匹配的实例
 */
ULyraEquipmentInstance* ULyraEquipmentManagerComponent::GetFirstInstanceOfType(TSubclassOf<ULyraEquipmentInstance> InstanceType)
{
	for (FLyraAppliedEquipmentEntry& Entry : EquipmentList.Entries) // 遍历装备条目
	{
		if (ULyraEquipmentInstance* Instance = Entry.Instance) // 获取实例
		{
			if (Instance->IsA(InstanceType)) // 检查实例类型匹配
			{
				return Instance; // 返回实例
			}
		}
	}

	return nullptr; // 未找到返回空
}

/**
 * 获取类型的所有实例
 * @param InstanceType - 实例类型
 * @return 所有匹配的实例数组
 */
TArray<ULyraEquipmentInstance*> ULyraEquipmentManagerComponent::GetEquipmentInstancesOfType(TSubclassOf<ULyraEquipmentInstance> InstanceType) const
{
	TArray<ULyraEquipmentInstance*> Results; // 结果数组
	for (const FLyraAppliedEquipmentEntry& Entry : EquipmentList.Entries) // 遍历装备条目
	{
		if (ULyraEquipmentInstance* Instance = Entry.Instance) // 获取实例
		{
			if (Instance->IsA(InstanceType)) // 检查实例类型匹配
			{
				Results.Add(Instance); // 添加实例到结果数组
			}
		}
	}
	return Results; // 返回结果数组
}